<?php

namespace App\Console\Commands;

use Illuminate\Console\Command;

class Fibonacci extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'fib {argument}';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'Command description';

    /**
     * Create a new command instance.
     *
     * @return void
     */
    public function __construct()
    {
        parent::__construct();
    }

    /**
     * Execute the console command.
     *
     * @return int
     */
    public function handle()
    {
        $argument = $this->argument('argument');

//        $this->info('==== Fib One =====');
//        $t3      = microtime(true);
//        $fib1    = $this->fib1($argument);
//        $notice2 = sprintf("Fib(%s)=%s", $argument, $fib1);
//        $this->info($notice2);
//        $t4 = microtime(true);
//        $this->info('==== Fib Two End ===== Total time is ' . ($t4 - $t3));

        $this->info('==== Fib Two =====');
        $t1      = microtime(true);
        $fib2    = $this->fib2($argument);
        $notice1 = sprintf("Fib(%s)=%s", $argument, $fib2);
        $this->info($notice1);
        $t2 = microtime(true);
        $this->info('==== Fib One End ===== Total time is ' . ($t2 - $t1));

        $this->info('==== Fib Three =====');
        $t5      = microtime(true);
//        $fib1    = $this->fib3($argument);
        $fib1    = $this->t($argument);
        $notice3 = sprintf("Fib(%s)=%s", $argument, $fib1);
        $this->info($notice3);
        $t6 = microtime(true);
        $this->info('==== Fib Three End ===== Total time is ' . ($t6 - $t5));

        return Command::SUCCESS;
    }

    private function fib1($num)
    {
        if ($num <= 0) {
            return -1;
        }

        if ($num <= 2) {
            return 1;
        }
        return $this->fib1($num - 1) + $this->fib1($num - 2);
    }

    private function fib2($num)
    {
        $fib    = [];
        $fib[0] = 1;
        $fib[1] = 1;
        for ($n = 2; $n <= $num; $n++) {
            $fib[$n] = $fib[$n - 1] + $fib[$n - 2];
        }
        return $fib[$num - 1];
    }

    private function fib3($num){
        $f = 0;
        $g = 1;
        $index = 2;
        while ($num>=$index){
            $g = $g+$f;
            $f = $g-$f;
            $index ++;
        }

        return $g;
    }


    public function t($index){
        $smaller = 1;
        $bigger  = 1;

        if ($index <= 2) {
            return 1;
        }

        while ($index > 2) {
            $bigger  = $smaller + $bigger;
            $smaller = $bigger - $smaller;
            $index--;
        }
        return $bigger;
    }


}
